﻿using Microsoft.Win32;
using OpcWorks.Open;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace OPCControl
{
    public partial class FormMain : Form
    {
        public FormMain()
        {
            InitializeComponent();
        }
        static readonly string opcWorksPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "OpcWorks");
        [DllImport("ole32.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
        static extern string ProgIDFromCLSID([In()] ref Guid clsid);
        static bool installed;
        static Dictionary<string, RpcItemBase> cache = new Dictionary<string, RpcItemBase>();

        private void FormMain_Load(object sender, EventArgs e)
        {
            txtPath.Text = opcWorksPath;
            CheckInstall();
            timerCheckInstall.Start();
            btnRefresh.Enabled = false;
            MessageBox.Show("OPC服务可能已处于启动状态，但如果想进行数据刷新实验，须点击启动按钮重启服务，因为每次重开此程序都无法控制上次服务启动时所创建的字段！");
        }
        void CheckInstall()
        {
            var g = Guid.Parse("76E342A4-290C-45BA-B1AF-6E6FD0692E1D");
            var progId = "";
            try
            {
                progId = ProgIDFromCLSID(ref g);
            }
            catch (Exception)
            {
            }
            installed = !string.IsNullOrWhiteSpace(progId);
            lblServiceStatus.Text = installed ? "服务已安装" : "服务未安装";
            btnInstall.Enabled = !installed;
            btnUninstall.Enabled = btnStart.Enabled = btnStop.Enabled = installed;
            if (installed)
            {
                txtPath.Text = Path.GetDirectoryName(GetServiceExecutable("OpcWorks Server"));
            }
        }
        private void BtnInstall_Click(object sender, EventArgs e)
        {
            //AppDomain.CurrentDomain.SetupInformation.PrivateBinPathProbe
            if (installed)
            {
                MessageBox.Show("服务已安装");
                return;
            }
            btnInstall.Enabled = false;
            ServerManager.RegServer(txtPath.Text);
        }

        private void BtnUninstall_Click(object sender, EventArgs e)
        {
            if (!installed)
            {
                MessageBox.Show("服务未安装");
                return;
            }
            btnUninstall.Enabled = false;
            ServerManager.StopOpcServer();
            ChannelManager.Instance.Quit();
            ServerManager.UnregServer(txtPath.Text);
        }

        private void TimerCheckInstall_Tick(object sender, EventArgs e)
        {
            CheckInstall();
        }
        string GetServiceExecutable(string name)
        {
            RegistryKey services = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\Services", false);
            if (services != null)
            {
                return (string)services.OpenSubKey(name).GetValue("ImagePath");
            }
            return null;
        }

        private void BtnStart_Click(object sender, EventArgs e)
        {
            cache[txtKey.Text] = new RpcItemBase { ItemID = txtKey.Text, DataType = "String", Access = AccessRights.ReadWrite, Value = txtValue.Text, Status = Results.Good };
            ChannelManager.Instance.Start(cache);
            ServerManager.StartOpcServer();
            btnRefresh.Enabled = true;
            MessageBox.Show("OPC服务已重启，服务可以反复启动多次，每次重启后所有的客户端请重新连接！");
        }

        private void BtnStop_Click(object sender, EventArgs e)
        {
            ServerManager.StopOpcServer();
            ChannelManager.Instance.Quit();
            btnRefresh.Enabled = false;
            MessageBox.Show("OPC服务已停止！");
        }

        private void BtnRefresh_Click(object sender, EventArgs e)
        {
            var item = cache[txtKey.Text];
            item.Value = txtValue.Text;
            item.Status = Results.Good;
            item.Timestamp = DateTime.Now;
            ChannelManager.Instance.RefreshItemValues(cache.Keys.ToArray());
        }
    }
}
